package cn.group7.padserver.controller;

import cn.group7.padserver.common.Flag;
import cn.group7.padserver.controller.responseformat.Code;
import cn.group7.padserver.controller.responseformat.Result;
import cn.group7.padserver.dao.UserDao;
import cn.group7.padserver.entity.Page;
import cn.group7.padserver.entity.PasswordParam;
import cn.group7.padserver.entity.UserInfo;
import cn.group7.padserver.entity.RegisterUser;
import cn.group7.padserver.pojo.Expert;
import cn.group7.padserver.pojo.Knowledge;
import cn.group7.padserver.pojo.User;
import cn.group7.padserver.service.ExpertService;
import cn.group7.padserver.service.UserService;
import cn.group7.padserver.utils.JwtTokenUtil;
import cn.hutool.core.util.StrUtil;
import io.swagger.annotations.ApiOperation;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.io.IOException;
import java.util.List;

/**
 * @author 谷汉斌
 * @description 用户请求控制器
 * @createTime 2024/7/31 下午8:06
 */
@Slf4j
@RestController
@RequestMapping("/users")
public class UserController {

    @Resource
    private UserService userService;

    @Resource
    private UserDao userDao;

    @Resource
    private ExpertService expertService;

    @Resource
    private UserDetailsService jwtUserDetailsService;

    @Resource
    private JwtTokenUtil jwtTokenUtil;


    /**
     * 用户登录之后，修改用户密码
     */
    @ApiOperation(value = "用户登录之后，修改用户密码")
    @PostMapping("/loginUpdatePassword")
    public Result loginUpdatePassword(@Validated @RequestBody PasswordParam passwordParam) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetails principal = (UserDetails) authentication.getPrincipal();
        String username = principal.getUsername();
        User user = userService.selectByUserName(username);
        //数据库密码
        String oldDataBasePassword = user.getPassword();
        //传过来的老密码
        String oldPassword = passwordParam.getOldPassword();
        if (!new BCryptPasswordEncoder().matches(oldPassword, oldDataBasePassword)) {
            return Result.builder().flag(Flag.FAIL.isCode()).code(Code.UPDATE_FAIL.getCode()).message(Code.UPDATE_FAIL.getInfo()).build();
        }
        user.setUserName(username);
        user.setPassword(passwordParam.getNewPassword());
        userService.update(user);
        return Result.builder().flag(Flag.SUCCESS.isCode())
                .code(Code.UPDATE_SUCCESS.getCode())
                .message(Code.UPDATE_SUCCESS.getInfo()).build();
    }

    /**
     * 用户登录之后，根据用户名修改个人基本信息
     */
    @ApiOperation(value = "用户登录之后，根据用户名修改个人基本信息")
    @PostMapping("/loginUpdateByUsername")
    public Result loginUpdateByUsername(@Validated @RequestBody User user) {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        UserDetails principal = (UserDetails) authentication.getPrincipal();
        String username = principal.getUsername();
        user.setUserName(username);
        boolean update = userService.loginUpdateByUsername(user);
        UserDetails userDetails = jwtUserDetailsService.loadUserByUsername(username);
        String token = jwtTokenUtil.generateToken(userDetails);
        return Result.builder().code(update ? Code.UPDATE_SUCCESS.getCode() : Code.UPDATE_FAIL.getCode())
                .data(update?token:null)
                .message(update ? Code.UPDATE_SUCCESS.getInfo() : Code.UPDATE_FAIL.getInfo())
                .flag(update ? Flag.SUCCESS.isCode() : Flag.FAIL.isCode())
                .build();
    }


    /**
     * 注册
     *
     * @return Result
     */
    @PostMapping("/register")
    public Result register(@RequestBody RegisterUser registerUser) {
        //校检信息
        if (null != registerUser) {
            if (!StrUtil.isBlank(registerUser.getUsername()) && !StrUtil.isBlank(registerUser.getPassword())) {
                //注册
                log.info("用户注册信息：{}", registerUser);
                if (userService.register(registerUser)) {
                    return Result.builder()
                            .flag(Flag.SUCCESS.isCode())
                            .code(Code.REGISTER_SUCCESS.getCode())
                            .message(Code.REGISTER_SUCCESS.getInfo())
                            .build();
                }
            }
        }
        log.info("无法注册用户信息：{}", registerUser);
        return Result.builder()
                .flag(Flag.FAIL.isCode())
                .code(Code.REGISTER_FAIL.getCode())
                .message(Code.REGISTER_FAIL.getInfo())
                .build();
    }

    /**
     * 经过Jwt验证后返回登录的用户信息
     *
     * @return Result
     */
    @GetMapping("/login-info")
    public Result loginInfo() {
        //获取当前登录的用户信息
        UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        User user = userService.selectByUserName(principal.getUsername());
        //封装信息
        UserInfo userInfo = UserInfo.builder()
                .username(user.getUserName())
                .nickName(user.getNickName())
                .role(user.getRole())
                .avatar(user.getAvatar())
                .phone(user.getPhone())
                .address(user.getAddress())
                .identityNum(user.getIdentityNum())
                .realName(user.getRealName())
                .integral(user.getIntegral())
                .credit(user.getCredit())
                .build();
        //返回信息
        return Result.builder()
                .flag(Flag.SUCCESS.isCode())
                .code(Code.GRANTED.getCode())
                .message(Code.GRANTED.getInfo())
                .data(userInfo)
                .build();
    }

    /**
     * 根据用户名查询用户信息
     *
     * @param username 用户名
     * @return Result
     */
    @ApiOperation(value = "根据用户名查询用户信息")
    @GetMapping("/selectByUsername/{username}")
    public Result selectByUsername(@PathVariable("username") String username) {
        User user = userService.selectByUserName(username);
        if (null != user) {
            UserInfo userInfo = UserInfo.builder()
                    .nickName(user.getNickName())
                    .address(user.getAddress())
                    .phone(user.getPhone())
                    .updateTime(user.getUpdateTime())
                    .build();
            return Result.builder()
                    .flag(Flag.SUCCESS.isCode())
                    .code(Code.QUERY_SUCCESS.getCode())
                    .message(Code.QUERY_SUCCESS.getInfo())
                    .data(userInfo)
                    .build();
        }
        return Result.builder()
                .flag(Flag.FAIL.isCode())
                .code(Code.QUERY_FAIL.getCode())
                .message(Code.QUERY_FAIL.getInfo())
                .build();
    }


    /**
     * 查询所有用户
     */
    @ApiOperation(value = "查询所有用户")
    @GetMapping
    public Result selectAll() {
        return Result.builder().flag(Flag.SUCCESS.isCode())
                .code(Code.QUERY_SUCCESS.getCode())
                .message(Code.QUERY_SUCCESS.getInfo())
                .data(userService.selectAll()).build();
    }


    /**
     * 增加用户
     */
    @ApiOperation(value = "增加用户")
    @PostMapping("/add")
    public Result add(@Valid @RequestBody User user) throws IOException {
        String userName = user.getUserName();
        User user1 = userDao.selectByPrimaryKey(userName);
        if (user1 != null) {
            return Result.builder().flag(Flag.FAIL.isCode()).code(Code.ADD_FAIL.getCode())
                    .message(Code.ADD_FAIL.getInfo()).build();
        }
        boolean add = userService.add(user);
        return Result.builder().flag(add ? Flag.SUCCESS.isCode() : Flag.FAIL.isCode())
                .code(add ? Code.ADD_SUCCESS.getCode() : Code.ADD_FAIL.getCode())
                .message(add ? Code.ADD_SUCCESS.getInfo() : Code.ADD_FAIL.getInfo()).build();
    }

    /**
     * 修改用户
     */
    @ApiOperation(value = "修改用户")
    @PutMapping("/update")
    public Result update(@Valid @RequestBody User user) {
        boolean update = userService.update(user);
        return Result.builder().flag(update ? Flag.SUCCESS.isCode() : Flag.FAIL.isCode())
                .code(update ? Code.UPDATE_SUCCESS.getCode() : Code.UPDATE_FAIL.getCode())
                .message(update ? Code.UPDATE_SUCCESS.getInfo() : Code.UPDATE_FAIL.getInfo()).build();
    }

    /**
     * 删除用户
     */
    @ApiOperation(value = "删除用户")
    @DeleteMapping("/delete/{username}")
    public Result delete(@PathVariable("username") String username) {
        boolean delete = userService.delete(username);
        return Result.builder().flag(delete ? Flag.SUCCESS.isCode() : Flag.FAIL.isCode())
                .code(delete ? Code.DELETE_SUCCESS.getCode() : Code.DELETE_FAIL.getCode())
                .message(delete ? Code.DELETE_SUCCESS.getInfo() : Code.DELETE_FAIL.getInfo()).build();
    }

    /**
     * 分页展示所有用户
     *
     * @param pageNum  页码
     * @param pageSize 每页数量
     * @return 用户列表
     */
    @ApiOperation(value = "分页展示所有用户")
    @GetMapping("/all")
    public Result selectOrders(@RequestParam("pageNum") Integer pageNum, @RequestParam(value = "pageSize", defaultValue = "6") Integer pageSize) {
        Page<User> page = userService.findPage(pageNum, pageSize);
        return Result.builder()
                .code(Code.QUERY_SUCCESS.getCode())
                .message(Code.QUERY_SUCCESS.getInfo())
                .data(page)
                .flag(Flag.SUCCESS.isCode()).build();
    }

    /**
     * 分页查询关键字用户
     *
     * @param pageNum  页码
     * @param pageSize 每页数量
     * @param keys     关键字
     * @return 用户页
     */
    @ApiOperation(value = "分页查询关键字用户")
    @GetMapping("/selectByKeys")
    public Result selectByKeys(@RequestParam("pageNum") Integer pageNum,
                               @RequestParam(value = "pageSize", defaultValue = "6") Integer pageSize,
                               @RequestParam("keys") String keys) {
        Page<Knowledge> page = userService.findPageByKeys(keys, pageNum, pageSize);
        return Result.builder()
                .code(Code.QUERY_SUCCESS.getCode())
                .message(Code.QUERY_SUCCESS.getInfo())
                .data(page)
                .flag(Flag.SUCCESS.isCode())
                .build();
    }


    /**
     * 查询专家详情
     */
    @ApiOperation("查询专家详情")
    @GetMapping("/searchexpert")
    public Result searchExpert() {
        //获取登陆的用户名
        UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String name = principal.getUsername();
        Expert expert = expertService.selectById(name);
        return Result.builder().flag(Flag.SUCCESS.isCode()).code(Code.QUERY_SUCCESS.getCode())
                .message(Code.QUERY_SUCCESS.getInfo()).data(expert).build();
    }

    /**
     * 查询所有专家详情
     */
    @ApiOperation("查询所有专家详情")
    @GetMapping("/searchallexpert")
    public Result searchAllExpert() {
        List<Expert> experts = expertService.selectAllExpert();
        return Result.builder().flag(Flag.SUCCESS.isCode()).code(Code.QUERY_SUCCESS.getCode())
                .message(Code.QUERY_SUCCESS.getInfo()).data(experts).build();
    }

    /**
     * 删除专家详情
     */
    @ApiOperation("删除专家详情")
    @DeleteMapping("/deleteexpert/{userName}")
    public Result deleteExpert(@PathVariable("userName") String userName) {
        boolean delete = expertService.delete(userName);
        return Result.builder().flag(delete ? Flag.SUCCESS.isCode() : Flag.FAIL.isCode())
                .code(delete ? Code.DELETE_SUCCESS.getCode() : Code.DELETE_FAIL.getCode())
                .message(delete ? Code.DELETE_SUCCESS.getInfo() : Code.DELETE_FAIL.getInfo()).build();
    }

    /**
     * 更新专家详情
     */
    @ApiOperation("更新专家详情")
    @PutMapping("/updateexpert")
    public Result updateExpert(@RequestBody Expert expert) {
        boolean update = expertService.updateById(expert);
        return Result.builder().flag(update ? Flag.SUCCESS.isCode() : Flag.FAIL.isCode())
                .code(update ? Code.UPDATE_SUCCESS.getCode() : Code.UPDATE_FAIL.getCode())
                .message(update ? Code.UPDATE_SUCCESS.getInfo() : Code.UPDATE_FAIL.getInfo()).build();
    }

    /**
     * 增加专家详情
     */
    @ApiOperation("增加专家详情")
    @PostMapping("/addexpert")
    public Result addExpert(@RequestBody Expert expert) {
        boolean insert = expertService.insert(expert);
        return Result.builder().flag(insert ? Flag.SUCCESS.isCode() : Flag.FAIL.isCode())
                .code(insert ? Code.ADD_SUCCESS.getCode() : Code.ADD_FAIL.getCode())
                .message(insert ? Code.ADD_SUCCESS.getInfo() : Code.ADD_FAIL.getInfo()).build();
    }

    /**
     * 增加或修改专家详情
     */
    @ApiOperation("增加或修改专家详情")
    @PostMapping("/addUpdexpert")
    public Result addUpdexpert(@RequestBody Expert expert) {

        //获取登陆的用户名
        UserDetails principal = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        String name = principal.getUsername();
        Expert expertExist = expertService.selectById(name);

        //设置专家用户名
        expert.setUserName(name);
        //如果专家存在，则更新，否则添加
        if (null != expertExist) {
            expertService.updateById(expert);
        } else {
            expertService.insert(expert);
        }
        return Result.builder().flag(Flag.SUCCESS.isCode()).code(Code.ADD_SUCCESS.getCode())
                .message(Code.ADD_SUCCESS.getInfo()).build();
    }

}
